﻿using BSWDEEPLEARNWrapper;
using BSWTradionWrapper;
using Station.Common.Rejudgment;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Station.Inspect.SuaModel
{
    public class Models
    {
        private const int maxNG = 50;
        private List<ModelBswSeg> ModelSegs = new List<ModelBswSeg>();
        private List<ModelBswClass> ModelSegClass = new List<ModelBswClass>();
        private List<ModelBswTV> ModelDefects = new List<ModelBswTV>();
        private List<ModelBswClass> ModelDefClass = new List<ModelBswClass>();

        //ModelHNcc ModelMark1 = new ModelHNcc();
        //ModelHNcc ModelMark2 = new ModelHNcc();

        public void Load(string path)
        {
            LoadBswSeg("分割算子", path + "\\SegModel", ref ModelSegs);
            LoadBswClass("S-C算子", path + "\\ClassModel", ref ModelSegClass);
            LoadBswTV("T算子", path + "\\TVModel", ref ModelDefects);
            LoadBswClass("T-C算子", path + "\\TVClassModel", ref ModelDefClass);
        }

        void LoadBswSeg(string name, string filePath, ref List<ModelBswSeg> models)
        {
            models.Clear();
            string strOk = "", strFail = "";
            if (Directory.Exists(filePath) == false)
                Directory.CreateDirectory(filePath);
            DirectoryInfo info = new DirectoryInfo(filePath);
            FileInfo[] files = info.GetFiles("*.pth");
            for (int i = 0; i < files.Length; i++)
            {
                var seg = new ModelBswSeg();
                if (seg.LoadModel(files[i].FullName))
                {
                    strOk += files[i].Name + ",";
                    models.Add(seg);
                }
                else
                    strFail += files[i].Name + ",";
            }
            bool hasOk = string.IsNullOrEmpty(strOk) == false;
            bool hasFail = string.IsNullOrEmpty(strFail) == false;
            if (hasOk || hasFail)
            {
                string strLog = name + "";
                if (hasOk)
                    strLog += "加载成功:" + strOk;
                if (hasFail)
                    strLog += "加载失败:" + strFail;
                MessageBox.Show(strLog);
            }
        }

        void LoadBswClass(string name, string filePath, ref List<ModelBswClass> models)
        {
            models.Clear();
            string strOk = "", strFail = "";
            if (Directory.Exists(filePath) == false)
                Directory.CreateDirectory(filePath);
            DirectoryInfo info = new DirectoryInfo(filePath);
            FileInfo[] files = info.GetFiles("*.pth");
            for (int i = 0; i < files.Length; i++)
            {
                var clas = new ModelBswClass();
                if (clas.LoadModel(files[i].FullName))
                {
                    strOk += files[i].Name + ",";
                    models.Add(clas);
                }
                else
                    strFail += files[i].Name + ",";
            }
            bool hasOk = string.IsNullOrEmpty(strOk) == false;
            bool hasFail = string.IsNullOrEmpty(strFail) == false;
            if (hasOk || hasFail)
            {
                string strLog = name + "";
                if (hasOk)
                    strLog += "加载成功:" + strOk;
                if (hasFail)
                    strLog += "加载失败:" + strFail;
                MessageBox.Show(strLog);
            }
        }

        void LoadBswTV(string name, string filePath, ref List<ModelBswTV> models)
        {
            models.Clear();
            string strOk = "", strFail = "";
            if (Directory.Exists(filePath) == false)
                Directory.CreateDirectory(filePath);
            DirectoryInfo info = new DirectoryInfo(filePath);
            FileInfo[] files = info.GetFiles("*.pth");
            for (int i = 0; i < files.Length; i++)
            {
                var clas = new ModelBswTV();
                if (clas.LoadModel(files[i].FullName))
                {
                    strOk += files[i].Name + ",";
                    models.Add(clas);
                }
                else
                    strFail += files[i].Name + ",";
            }
            bool hasOk = string.IsNullOrEmpty(strOk) == false;
            bool hasFail = string.IsNullOrEmpty(strFail) == false;
            if (hasOk || hasFail)
            {
                string strLog = name + "";
                if (hasOk)
                    strLog += "加载成功:" + strOk;
                if (hasFail)
                    strLog += "加载失败:" + strFail;
                MessageBox.Show(strLog);
            }
        }

        bool RunBswClassModel(Bitmap img, int markID, int libID,int cx,int cy,float threshold, List<ModelBswClass> models)
        {
            foreach(var model in models)
            {
                if(model.InRange(libID) && model.Run(img,cx,cy,threshold))
                    return true;
            }
            return false;
        }

        public List<RectErr> RunBswSegModel(Bitmap img,int markID,int libID,bool bBswClassify,double sThreshold,float cThreshold,float minSize,float minArea)
        {
            var rectErrs = new List<RectErr>();
            if (img!=null)
            {
                var segRes = new List<SegResult>();
                foreach (var seg in ModelSegs)
                {
                    if(seg.InRange(libID))
                    {
                        seg.Run(img, sThreshold, out List<SegResult> res);
                        foreach(var item in res)
                        {
                            bool bNG = true;
                            if(bBswClassify)
                            {
                                int l = item.points.Min(p => p.X);
                                int r = item.points.Max(p => p.X);
                                int t = item.points.Min(p => p.Y);
                                int b = item.points.Max(p => p.Y);
                                int w = r - l;
                                int h = b - t;
                                if (minSize <= w && minSize <= h && minArea<w*h)
                                    bNG = RunBswClassModel(img, markID, libID, (l + r) / 2, (t + b) / 2, cThreshold, ModelSegClass);
                                else
                                    bNG = false;
                            }
                            if(bNG)
                                segRes.Add(item);
                        }
                    }
                        
                }
                segRes.Sort((a, b) => (a.prob < b.prob ? -1 : 1));
                int min = Math.Min(segRes.Count, maxNG);
                for (int i = 0; i < min; i++)
                {
                    var item = segRes[i];
                    int l = item.points.Min(p => p.X);
                    int r = item.points.Max(p => p.X);
                    int t = item.points.Min(p => p.Y);
                    int b = item.points.Max(p => p.Y);
                    rectErrs.Add(new RectErr()
                    {
                        Name = item.name,
                        Score = item.prob,
                        rect = new Rectangle(l, t, r - l, b - t)
                    });
                }
            }
            return rectErrs;
        }

        public List<RectErr> RunBswDefect(Bitmap img, int markID, int libID, bool bBswClassify, float tThreshold, float cThreshold, float minSize,float minArea)
        {
            var rectErrs = new List<RectErr>();
            if(img!=null)
            {
                var defRes = new List<BSW_DefectResultCS>();
                foreach (var def in ModelDefects)
                {
                    if (def.InRange(libID))
                    {
                        def.RunAsDefect(img, markID, libID, tThreshold, out List<BSW_DefectResultCS> res);
                        foreach (var item in res)
                        {
                            bool bNG = true;
                            if (bBswClassify)
                            {
                                int l = (int)item.out_points.Min(p => p.X);
                                int r = (int)item.out_points.Max(p => p.X);
                                int t = (int)item.out_points.Min(p => p.Y);
                                int b = (int)item.out_points.Max(p => p.Y);
                                int w = r - l;
                                int h = b - t;
                                if (minSize <= w && minSize <= h && minArea <w*h)
                                    bNG = RunBswClassModel(img, markID, libID, (l + r) / 2, (t + b) / 2, cThreshold, ModelDefClass);
                                else
                                    bNG = false;
                            }
                            if (bNG)
                                defRes.Add(item);
                        }
                    }
                }
                defRes.Sort((a, b) => (a.score < b.score ? -1 : 1));
                int min = Math.Min(defRes.Count, maxNG);
                for (int i = 0; i < min; i++)
                {
                    var item = defRes[i];
                    int l = (int)item.out_points.Min(p => p.X);
                    int r = (int)item.out_points.Max(p => p.X);
                    int t = (int)item.out_points.Min(p => p.Y);
                    int b = (int)item.out_points.Max(p => p.Y);
                    rectErrs.Add(new RectErr()
                    {
                        Score = item.score,
                        rect = new Rectangle(l, t, r - l, b - t)
                    });
                }
            }
            return rectErrs;
        }
    }
}
